package com.note.app.websocket;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.note.app.dto.collaboration.CollaborationMessageDTO;
import com.note.app.dto.collaboration.CollaborationOperationDTO;
import com.note.app.service.CollaborationService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.messaging.handler.annotation.DestinationVariable;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Controller;

/**
 * WebSocket消息处理器
 */
@Slf4j
@Controller
@RequiredArgsConstructor
public class CollaborationWebSocketHandler {
    
    private final SimpMessagingTemplate messagingTemplate;
    private final CollaborationService collaborationService;
    private final ObjectMapper objectMapper;
    
    /**
     * 处理加入会话消息
     */
    @MessageMapping("/collaboration/{sessionId}/join")
    public void handleJoinMessage(@DestinationVariable Long sessionId, @Payload CollaborationMessageDTO message) {
        try {
            log.info("收到加入会话消息: sessionId={}, userId={}", sessionId, message.getSenderId());
            // 加入会话处理逻辑
            collaborationService.joinSession(sessionId, message.getSenderId(), message.getContent());
            
            // 广播消息给会话中的所有参与者
            messagingTemplate.convertAndSend("/topic/collaboration/" + sessionId + "/events", message);
        } catch (Exception e) {
            log.error("处理加入会话消息异常", e);
        }
    }
    
    /**
     * 处理离开会话消息
     */
    @MessageMapping("/collaboration/{sessionId}/leave")
    public void handleLeaveMessage(@DestinationVariable Long sessionId, @Payload CollaborationMessageDTO message) {
        try {
            log.info("收到离开会话消息: sessionId={}, userId={}", sessionId, message.getSenderId());
            // 离开会话处理逻辑
            collaborationService.leaveSession(sessionId, message.getSenderId());
            
            // 广播消息给会话中的所有参与者
            messagingTemplate.convertAndSend("/topic/collaboration/" + sessionId + "/events", message);
        } catch (Exception e) {
            log.error("处理离开会话消息异常", e);
        }
    }
    
    /**
     * 处理操作消息
     */
    @MessageMapping("/collaboration/{sessionId}/operation")
    public void handleOperationMessage(@DestinationVariable Long sessionId, @Payload CollaborationMessageDTO message) {
        try {
            log.info("收到操作消息: sessionId={}, userId={}", sessionId, message.getSenderId());
            
            // 解析操作内容
            OperationRequest operationRequest = objectMapper.readValue(message.getContent(), OperationRequest.class);
            
            // 处理操作
            CollaborationOperationDTO operation = collaborationService.handleOperation(
                    message.getSenderId(),
                    sessionId,
                    operationRequest.getOpType(),
                    operationRequest.getPosition(),
                    operationRequest.getContent()
            );
            
            // 操作处理完成后，将结果设置到消息中
            message.setContent(objectMapper.writeValueAsString(operation));
            
            // 广播消息给会话中的所有参与者
            messagingTemplate.convertAndSend("/topic/collaboration/" + sessionId + "/operations", message);
        } catch (Exception e) {
            log.error("处理操作消息异常", e);
        }
    }
    
    /**
     * 处理光标位置消息
     */
    @MessageMapping("/collaboration/{sessionId}/cursor")
    public void handleCursorMessage(@DestinationVariable Long sessionId, @Payload CollaborationMessageDTO message) {
        try {
            log.info("收到光标位置消息: sessionId={}, userId={}", sessionId, message.getSenderId());
            
            // 更新光标位置
            collaborationService.updateCursorPosition(sessionId, message.getSenderId(), message.getContent());
            
            // 广播消息给会话中的所有参与者
            messagingTemplate.convertAndSend("/topic/collaboration/" + sessionId + "/cursors", message);
        } catch (Exception e) {
            log.error("处理光标位置消息异常", e);
        }
    }
    
    /**
     * 操作请求内部类
     */
    private static class OperationRequest {
        private int opType;
        private String position;
        private String content;
        
        public int getOpType() {
            return opType;
        }
        
        public void setOpType(int opType) {
            this.opType = opType;
        }
        
        public String getPosition() {
            return position;
        }
        
        public void setPosition(String position) {
            this.position = position;
        }
        
        public String getContent() {
            return content;
        }
        
        public void setContent(String content) {
            this.content = content;
        }
    }
} 